#include "shell.h"
#include "shell_inner.h"
#if (CONFIG_MEM_ENABLE)
#include "mem_sal.h"
#endif

/* shell common command */

#ifdef CONFIG_SHELL_ENABLE

/*
http://patorjk.com/software/taag/#p=display&f=Graffiti&t=
Font Name: Small Slant
   ____            ___  __________  ____  ______       ____
  / __/______ ___ / _ \/_  __/ __ \/ __/ / __/ /  ___ / / /
 / _// __/ -_) -_) , _/ / / / /_/ /\ \  _\ \/ _ \/ -_) / / 
/_/ /_/  \__/\__/_/|_| /_/  \____/___/ /___/_//_/\__/_/_/  

*/

#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_RESET   "\x1b[0m"

static const char *system_log[4]=
{
    "   ____            ___  __________  ____  ______       ____",
    "  / __/______ ___ / _ \\/_  __/ __ \\/ __/ / __/ /  ___ / / /",
    " / _// __/ -_) -_) , _/ / / / /_/ /\\ \\  _\\ \\/ _ \\/ -_) / / ",
    "/_/ /_/  \\__/\\__/_/|_| /_/  \\____/___/ /___/_//_/\\__/_/_/  ",
};

void shell_system_show_version(void)
{
    uint8_t i = 0;
	shell_printf("\n");
#if 0
	printf("%s\n", system_log[i++]);
	printf("%s * FreeRTOS:%s\n", system_log[i++], tskKERNEL_VERSION_NUMBER);
	printf("%s * Shell:V%s\n", system_log[i++], SHELL_VERSION);
	printf("%s * build %s\n", system_log[i++], __DATE__);
#else
	shell_printf("\x1b[34m%s\x1b[0m\n", system_log[i++]);
	shell_printf("\x1b[34m%s\x1b[0m * %s:%s\n", system_log[i++], os_get_name(), os_get_version());
	shell_printf("\x1b[34m%s\x1b[0m * Shell:V%s\n", system_log[i++], SHELL_VERSION);
	shell_printf("\x1b[34m%s\x1b[0m * build %s\n", system_log[i++], __DATE__);
#endif
    
	shell_printf("\n");
}

static int shell_cmd_version(int argc, char **argv)
{
    shell_system_show_version();
    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_cmd_version, version, show version information);

static int shell_cmd_uname(int argc, char **argv)
{
    
    shell_printf("OS: %s %s\n", os_get_name(), os_get_version());
    shell_printf("Build: ");
#if defined(__CC_ARM) 		        	/* ARM Compiler */
	shell_printf("ARMCC V%d.%02d(build %d) ", __ARMCC_VERSION/1000000, (__ARMCC_VERSION/10000)%100, __ARMCC_VERSION%1000);
#elif defined (__GNUC__)                /* GNU GCC Compiler */
	shell_printf("GCC V%d.%d.%d ", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);	
#else
    shell_printf("unknow ");
#endif
    shell_printf("in %s %s\n", __DATE__, __TIME__);

    shell_port_chip_info();

    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_cmd_uname, uname, print system information);

static __inline void object_split(int len)
{
    while (len--) shell_printf("-");
	shell_printf("\n");
}

static int shell_cmd_free(int argc, char **argv)
{
    uint32_t total, used, free, usage;

    /* split */
    object_split(80);

    shell_printf("%27s%12s%12s%12s\n","total", "used", "free", "usage");

    /* mem os */
    total = os_get_heap_total_size(); // configTOTAL_HEAP_SIZE;
    free = os_get_heap_free_size();
    used = total - free;
	usage = (used * 100) / total;
    shell_printf("%-15s", "Mem OS:");
    shell_printf("%12d%12d%12d%11d%%\n",total, used, free, usage);

    /* SRAM IN */
#if (CONFIG_MEM_ENABLE)
    {
        int i;
        _mem_sal_info_t info;
        void (*mem_func[])(_mem_sal_info_t *) = 
        {
        #if (CONFIG_MEM_AREA_DTCM_ENABLE)
            mem_dtcm_get_info,
        #else
            NULL,
        #endif

        #if (CONFIG_MEM_AREA_AXI_ENABLE)
            mem_axi_get_info,
        #else
            NULL,
        #endif

        #if (CONFIG_MEM_AREA_SRAM1_ENABLE)
            mem_sram1_get_info,
        #else
            NULL,
        #endif
    
        #if (CONFIG_MEM_AREA_SRAM2_ENABLE)
            mem_sram2_get_info,
        #else
            NULL,
        #endif
        };
        
        for (i = 0; i < 4; i++)
        {
            if (mem_func[i] == NULL) continue;

            mem_func[i](&info);
            total = info.total;
            used = info.used;
            free = total - used;
            usage = (used * 100) / total;
            // shell_printf("%-12s", "Mem %5s HEAP:", info.name);
            shell_printf("Mem HEAP %-5s:", info.name);
            shell_printf("%12d%12d%12d%11d%%\n", total, used, free, usage);
        }
        
    }
#endif
    /* split */
    object_split(80);
    
    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_cmd_free, free, show the memory usage in the system);

#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
static int shell_cmd_ps(int argc, char **argv)
{
    uint8_t flag = 0;
    char *buff = NULL;

	object_split(80);

    buff = malloc(512);
    if (buff == NULL)
    {
        shell_printf("buff malloc fail\n");
        return -1;
    }

#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
    flag++;
    shell_printf("Task Name      STAT     PRIO    STACK   ID      CORE\n");
    vTaskList((char *)buff);
    shell_printf("%s\n", buff);
#endif

#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
    flag++;
    shell_printf("Task Name       CNT             %%CPU\n");
    vTaskGetRunTimeStats((char *)buff);
    shell_printf("%s\n", buff);
#endif
    free(buff);
	
    if (flag == 0)
    {
        shell_printf("CONFIG_FREERTOS_USE_TRACE_FACILITY or CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS should define\n");
    }

	object_split(80);

    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_cmd_ps, ps, process status);
#endif 

static int shell_cmd_reboot(int argc, char **argv)
{
    shell_printf("system reboot...\n");
    shell_port_reboot();
    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_cmd_reboot, reboot, reset system);

static int shell_cmd_clear(int argc, char **argv)
{
    shell_printf("\x1b[2J\x1b[H");
    return 0;
}
SHELL_CMD_EXPORT_ALIAS(shell_cmd_clear, clear, clear the terminal screen)

#if 0
static int test(int argc, char **argv)
{
    printf(ANSI_COLOR_RED     "_This text is _RED!"     ANSI_COLOR_RESET "\r\n");
    printf(ANSI_COLOR_GREEN   "_This text is _GREEN!"   ANSI_COLOR_RESET "\r\n");
    printf(ANSI_COLOR_YELLOW  "_This text is _YELLOW!"  ANSI_COLOR_RESET "\r\n");
    printf(ANSI_COLOR_BLUE    "_This text is _BLUE!"    ANSI_COLOR_RESET "\r\n");
    printf(ANSI_COLOR_MAGENTA "_This text is _MAGENTA!" ANSI_COLOR_RESET "\r\n");
    printf(ANSI_COLOR_CYAN    "_This text is _CYAN!"    ANSI_COLOR_RESET "\r\n");

    return 0;
}
SHELL_CMD_EXPORT(test, test func);
#endif

#endif




